package com.dongzili.easysearch.demos;

import kilim.Mailbox;
import kilim.Pausable;
import kilim.Task;

import java.sql.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Kilim协程在数据库分批次分页查询中的应用(适合数据全量同步使用)
 */
public class DatabaseQueryInKilim {
    int totalPages = 100;  // 总页数（100万行 / 每页1万行）
    int pageSize = 10000;  // 每页行数
    QueryWorker[] workers = new QueryWorker[totalPages];  // 任务数组
    AtomicInteger remaining = new AtomicInteger(totalPages);  // 剩余查询数
    
    // 数据库连接信息（请根据实际环境修改）
    private static final String DB_DRIVER = "com.mysql.cj.jdbc.Driver";
    private static final String DB_URL = "jdbc:mysql://127.0.0.1:3306/wlxtdb?allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "root";
    private static final String QUERY_SQL = "SELECT * FROM s_relation order by ID ASC LIMIT ?, ?";

    /**
     * 查询工作器，处理实际数据库分页查询
     */
    public class QueryWorker extends Task<Object> {
        Mailbox<Integer> pageSignal = new Mailbox<>();  // 接收页码的邮箱
        int pageNum;  // 页码
        long queryTime;  // 实际查询耗时（毫秒）

        @Override
        public void execute() throws Pausable {
            Connection conn = null;
            PreparedStatement pstmt = null;
            ResultSet rs = null;
            
            try {
                // 等待页码信号
                pageNum = pageSignal.get();
                
                // 建立数据库连接
                conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
                pstmt = conn.prepareStatement(QUERY_SQL);
                
                // 设置分页参数（LIMIT  offset, row_count）
                int offset = (pageNum - 1) * pageSize;
                pstmt.setInt(1, offset);
                pstmt.setInt(2, pageSize);
                
                // 执行查询并记录耗时
                long startTime = System.currentTimeMillis();
                rs = pstmt.executeQuery();

                // 处理结果集（统计行数，模拟实际处理）
                int rowCount = 0;
                while (rs.next()) {
//                    long id = rs.getLong ("ID");
//                    System.out.println(rowCount+ " --> "+id);
                    if (pageNum>=99 && rowCount>=9999){
                        System.out.println(pageNum + " --> 最后一行ID: " + rs.getLong("ID"));
                    }
                    rowCount++;  // 实际场景中可处理每行数据
                }
//                while (rs.last()){
//                    System.out.println("最后一行ID: " + rs.getLong("ID"));
//                }

                queryTime = System.currentTimeMillis() - startTime;
                
                System.out.printf("分页查询完成 - 页码: %d, 实际行数: %d, 耗时: %dms%n",
                        pageNum, rowCount, queryTime);

            } catch (SQLException e) {
                System.err.printf("分页查询失败 - 页码: %d, 错误: %s%n",
                        pageNum, e.getMessage());
            } finally {
                // 关闭资源
                try {
                    if (rs != null) rs.close();
                    if (pstmt != null) pstmt.close();
                    if (conn != null) conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                // 减少剩余计数
                remaining.decrementAndGet();
            }
        }
    }

    /**
     * 启动模拟
     */
    void runSimulation() {
        // 初始化所有查询工作器并启动
        for (int i = 0; i < totalPages; i++) {
            (workers[i] = new QueryWorker()).start();
        }

//        try {
//            Thread.sleep(10000);
//        } catch (InterruptedException e) {
//            throw new RuntimeException(e);
//        }
        // 发送页码信号（1到100页）pageSignal发送之后开始执行查询操作，不然就等待
        for (int i = 0; i < totalPages; i++) {
            workers[i].pageSignal.putnb(i + 1);  // 页码从1开始
        }

        // 监控进度
        for (int curr, prev = totalPages; (curr = remaining.get()) > 0; prev = curr, sleep()) {
            if (curr != prev) {  // 仅在数量变化时输出
                System.out.printf("查询进度: 已完成%d/%d页, 剩余%d页%n",
                        totalPages - curr, totalPages, curr);
            }
        }
    }

    // 线程睡眠
    static void sleep() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

    public static void main(String[] args) {
        // 加载数据库驱动
        try {
            Class.forName(DB_DRIVER);
        } catch (ClassNotFoundException e) {
            System.err.println("数据库驱动加载失败: " + e.getMessage());
            return;
        }
        
        // Kilim初始化
        if (kilim.tools.Kilim.trampoline(false, args)) return;

        long startTime = System.currentTimeMillis();
        System.out.println("开始对wlxtdb.s_relation表进行分页查询模拟（100万行，每页1万行）...");
        DatabaseQueryInKilim sim = new DatabaseQueryInKilim();
        sim.runSimulation();
        
        // 等待所有任务结束
        Task.idledown();
        long totalTime = System.currentTimeMillis() - startTime;
        System.out.println("\n所有分页查询完成!");
        System.out.printf("总页数: %d, 未完成页数: %d 总耗时: %d ms",
                sim.totalPages, sim.remaining.get(), totalTime);
    }
}
    